/*
** Copyright (c) 2008 Mobile GCalendar
**
** Permission is hereby granted, free of charge, to any person
** obtaining a copy of this software and associated documentation
** files (the "Software"), to deal in the Software without
** restriction, including without limitation the rights to use,
** copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the
** Software is furnished to do so, subject to the following
** conditions:
**
** The above copyright notice and this permission notice shall be
** included in all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
** OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
** HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
** WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
** OTHER DEALINGS IN THE SOFTWARE.
*/

/**
 *
 */
package au.edu.mq.comp.itec800.mgc.util;

import java.util.ArrayList;


/**
 * The CommandLine class implements a simple command-line arguments parsing
 * facility.
 *
 * It performs simple parsing of a standard command-line syntax and
 * can be used by 3rd parties programs to detect commands and their
 * arguments in interactive shells or command based interpreters.
 *
 *
 * @author Laurent Malvert [laurent.malvert@students.mq.edu.au]
 */
public class CommandLine
{
  private String    command   = null;
  private String[]  arguments = null;


  public CommandLine()
  {
    this(null, (String[])null);
  }

  public CommandLine(final String command, final String ... arguments)
  {
    this.command    = (command != null) ? command : "";
    this.arguments  = (arguments != null) ? arguments : new String[0];
  }

  /**
   * Parses a command-line string and returns a CommandLine object.
   *
   * If the given command-line is not valid (null) or does not provide any
   * arguments, default empty strings and arrays are used.
   *
   * @param line
   *            the command-line to be parsed
   * @return
   *            the array of string containing {command, args}
   */
  public static CommandLine load(final String line)
  {
    final CommandLine       cl  = new CommandLine();

    cl.parse(line);
    return (cl);
  }

  /**
   * Parses a command-line string and using the current CommandLine object.
   *
   * If the given command-line is not valid (null) or does not provide any
   * arguments, default empty strings and arrays are used.
   *
   * @param line
   *            the command-line to be parsed
   */
  public void               parse(final String line)
  {
    final String  cline = StringUtils.clean(line);

    if (line != null)
    {
      final String[]        tokens  = cline.split("[ \t+]", 2);

      if (tokens.length > 0)
      {
        command = tokens[0];
      }
      if (tokens.length > 1)
      {
        // TODO: add code here to cut tokens[1] into an array of string
        // according to UNIX-like whitespacing and quoting
        arguments = tokens[1].split("[ \t]+");
      }
    }
  }

  public String             getCommand()
  {
    return (command);
  }

  public String[]           getArguments()
  {
    return (arguments);
  }

  /* (non-Javadoc)
   * @see java.lang.Object#toString()
   */
  @Override
  public String             toString()
  {
    final StringBuffer      sb  = new StringBuffer(512);

    sb.append("{");
    sb.append(getCommand());
    sb.append("} ");
    for (final String arg : getArguments())
    {
      sb.append("[");
      sb.append(arg);
      sb.append("]");
    }
    return (sb.toString());
  }

  public CommandLine[]      loadCommands(final String line)
  {
    CommandLine[]           clsa = new CommandLine[0];

    if (line != null)
    {
      final ArrayList<CommandLine>  cls = new ArrayList<CommandLine>();

      /*
       * TODO:
       *  implement multiple command parsing here
       */
      cls.toArray(clsa = new CommandLine[cls.size()]);
    }
    return (clsa);
  }

  class CommandLineException extends Exception
  {
    private static final long serialVersionUID  = -8840349450057843801L;

    private String            line              = null;
    private int               index             = 0;

    public CommandLineException(final String line,
                                final int index,
                                final String message)
    {
      super(message);
      this.line   = line;
      this.index  = index;
    }

    public int    getIndex()
    {
      return (index);
    }

    public String getLine()
    {
      return (line);
    }
  }

  public static void        test(final String testLine)
  {
    if (testLine != null)
    {
      final CommandLine cl  = CommandLine.load(testLine);

      System.out.println("[" + testLine + "]");
      System.out.println("command: " + cl.getCommand());
      for (final String arg : cl.getArguments())
      {
        System.out.println(" > " + arg);
      }
      System.out.println("");
    }
  }

//  public static void        main(final String[] args)
//  {
//    test("test");
//    test("test arg1");
//    test("test arg1 arg2 arg3 arg4");
//    test("test \"arg 1\" arg2 \"argument num'3\"");
//  }
}
